package projetomsn.Client.ServerInterface;

import java.net.InetAddress;
import java.net.Socket;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import projetomsn.Server.ServerInterface;
import projetomsn.Server.ServerSettings;

/**
 * Classe para gerenciamento do usuário
 */
public class ClientManager {

    /**
     * Socket para mensagens de recebidas
     */
    private Socket clientSocket;
    /**
     * Endereço do servidor do messenger
     */
    private String serverAddress; 
    /**
     * Recebe mensagens do multicast
     */
    private ThreadToGetMessages threadToGetMessage;
    /**
     * Status da conexão
     */
    private boolean isOn = false; 
    /**
     * Executor para o servidor
     */
    private ExecutorService executeThread;
    /**
     * Informar que o usuário está desconctado
     */
    public static String DISCONNECT_STRING="DISCONNECT";

    /**
     * Metodo construtor para o gerenciador de usuário
     * @param address 
     */
    public ClientManager(String address) {
        serverAddress = address; // armazena endereço do servidor
        executeThread = Executors.newCachedThreadPool();
    }

 
    /**
     * Conecta ao servidor e manda mensagens para o sevidor
     * @param serverInterface 
     */
    public void connect(ServerInterface serverInterface) {
        if (isOn) {
            return; // se ja isOn, retorna imediatamente
        }
        try 
        {
            clientSocket = new Socket(
                    InetAddress.getByName(serverAddress),12345);

            // cria Runnable para receber mensagens
            threadToGetMessage = new ThreadToGetMessages(serverInterface);
            executeThread.execute(threadToGetMessage); // executa Runnable
            isOn = true; // atualiza sinalizador de isOn 
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
   
    /**
     * Desconecta com o servidor e apaga o registro do servidor
     * @param serverInterface 
     */
    public void disconnect(ServerInterface serverInterface) {
        if (!isOn) {
            return; // se não isOn, retorna imediatamente
        }
        try // para serverInterface e desconecta do servidor
        {
            // notifica o servidor que o cliente está desconectando
            Runnable disconnecter = new ThreadToSendMessage(clientSocket, "",
                    "DISCONNECT");
            Future disconnecting = executeThread.submit(disconnecter);
            disconnecting.get(); // espera pela mensagem desconexão ser mandada
            threadToGetMessage.clientOff(); // para threadToGetMessage
            clientSocket.close(); // fecha Socket de saida
        } catch (ExecutionException exception) {
            exception.printStackTrace();
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }

        isOn = false; 
    }

    /**
     * Envia mensagem ao servidor
     * @param from
     * @param message 
     */
    public void send(String from, String message) {
        if (!isOn) {
            return; // se o usuário não está on ele retorna imediatamente
        }   
        executeThread.execute(
                new ThreadToSendMessage(clientSocket, from, message));
    }
}
